home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS02.ADF / C / usq.c < prev    next >
C/C++ Source or Header  |  1989-05-30  |  12KB  |  379 lines

  1. /* Program to unsqueeze files formed by sq.com
  2.  *
  3.  * Useage:
  4.  *
  5.  *      usq [-count] [-fcount] [file1] [file2] ... [filen]
  6.  *
  7.  * where file1 through filen represent one or more files to be compressed,
  8.  * and the following options may be specified:
  9.  *
  10.  *      -count          Previewing feature: redirects output
  11.  *                      files to standard output with parity stripped
  12.  *                      and unprintables except CR, LF, TAB and  FF
  13.  *                      converted to periods. Limits each file
  14.  *                      to first count lines.
  15.  *                      Defaults to console, but see below how
  16.  *                      to capture all in one file for further
  17.  *                      processing, such as by PIP.
  18.  *                      Count defaults to a very high value.
  19.  *                      No CRC check is performed when previewing.
  20.  *                      Use drive: to cancel this.
  21.  *
  22.  *      -fcount         Same as -count except formfeed
  23.  *                      appended to preview of each file.
  24.  *                      Example: -f10.
  25.  *
  26.  * If no such items are given on the command line you will be
  27.  * prompted for commands (one at a time). An empty command
  28.  * terminates the program.
  29.  *
  30.  * The unsqueezed file name is recorded in the squeezed file.
  31.  * 
  32.  */
  33. /* CHANGE HISTORY:
  34.  * 1.3  Close inbuff to avoid exceeding maximum number of
  35.  *      open files. Includes rearranging error exits.
  36.  * 1.4  Add -count option to allow quick inspection of files.
  37.  * 1.5  Break up long lines of introductory text
  38.  * 1.5  -count no longer appends formfeed to preview of each file.
  39.  *      -fcount (-f10, -F10) does append formfeed.
  40.  * 1.6  Modified to work correctly under MP/M II (DIO.C change) and
  41.  *      signon message shortened.
  42.  * 2.0  Modified to work with CI-C86 compiler (CP/M-86 and MS-DOS)
  43.  * 2.1  Modified for use in MLINK
  44.  * 2.2  Modified for use with optimizing CI-C86 compiler (MS-DOS)
  45.  * 3.0  Generalized for use under UNIX
  46.  *
  47.  * 3.2  Ported to Amiga & Lattice
  48.  *      Rick Schaeffer [70120,174] 12/03/85
  49.  * 3.25 Lattice warning errors corrected : John Hodgson 1/14/86/ 
  50.  */
  51.  
  52. #include <stdio.h>
  53. #define ERROR -1
  54.  
  55. /* Definitions and external declarations */
  56.  
  57. #define RECOGNIZE 0xFF76        /* unlikely pattern */
  58.  
  59. /* *** Stuff for first translation module *** */
  60.  
  61. #define DLE 0x90
  62.  
  63. unsigned int crc;        /* error check code */
  64.  
  65. /* *** Stuff for second translation module *** */
  66.  
  67. #define SPEOF 256       /* special endfile token */
  68. #define NUMVALS 257     /* 256 data values plus SPEOF*/
  69. #define LARGE 30000
  70.  
  71. /* Decoding tree */
  72. struct {
  73.         int children[2];        /* left, right */
  74. } dnode[NUMVALS - 1];
  75.  
  76. int bpos;        /* last bit position read */
  77. int curin;       /* last byte value read */
  78.  
  79. /* Variables associated with repetition decoding */
  80. int repct;       /*Number of times to retirn value*/
  81. int value;       /*current byte value or EOF */
  82. #define VERSION "3.2   12/03/85"
  83.  
  84. /* This must follow all include files */
  85. unsigned int dispcnt;   /* How much of each file to preview */
  86. char    ffflag;         /* should formfeed separate preview from different files */
  87.  
  88. main(argc, argv)
  89. int argc;
  90. char *argv[];
  91. {
  92.         int i,c;
  93.         char inparg[16];        /* parameter from input */
  94.  
  95.         dispcnt = 0;    /* Not in preview mode */
  96.  
  97.         printf("File unsqueezer version %s (original author: R. Greenlaw)\n\n", VERSION);
  98.  
  99.         /* Process the parameters in order */
  100.         for(i = 1; i < argc; ++i)
  101.                 obey(argv[i]);
  102.  
  103.         if(argc < 2) {
  104.                 printf("Enter file names, one line at a time, or type <RETURN> to quit.");
  105.                 do {
  106.                         printf("\n*");
  107.                         for(i = 0; i < 16; ++i) {
  108.                                 if((c = getchar()) == EOF)
  109.                                         c = '\n';       /* force empty (exit) command */
  110.                                 if((inparg[i] = c) == '\n') {
  111.                                         inparg[i] = '\0';
  112.                                         break;
  113.                                 }
  114.                         }
  115.                         if(inparg[0] != '\0')
  116.                                 obey(inparg);
  117.                 } while(inparg[0] != '\0');
  118.         }
  119. }
  120.  
  121. /* eject^Leject */
  122.  
  123. obey(p)
  124. char *p;
  125. {
  126.         char *q;
  127.  
  128.         if(*p == '-') {
  129.                 if(ffflag = ((*(p+1) == 'F') || (*(p+1) == 'f')))
  130.                         ++p;
  131.                 /* Set number of lines of each file to view */
  132.                 dispcnt = 65535;        /* default */
  133.                 if(*(p+1))
  134.                         if((dispcnt = atoi(p + 1)) == 0)
  135.                                 printf("\nBAD COUNT %s", p + 1);
  136.                 return 0;
  137.         }       
  138.  
  139.         /* Check for ambiguous (wild-card) name */
  140.         for(q = p; *q != '\0'; ++q)
  141.                 if(*q == '*' || *q == '?') {
  142.                         printf("\nCan't accept ambiguous name %s", p);
  143.                         return 0;
  144.                 }
  145.  
  146.         unsqueeze(p);
  147. }
  148.  
  149. /* eject^Leject */
  150.  
  151. unsqueeze(infile)
  152. char *infile;
  153. {
  154.         FILE *inbuff, *outbuff; /* file buffers */
  155.         int i, c;
  156.         char cc;
  157.  
  158.         char *p;
  159.         unsigned int filecrc;   /* checksum */
  160.         int numnodes;           /* size of decoding tree */
  161.         char outfile[128];      /* output file name */
  162.         unsigned int linect;    /* count of number of lines previewed */
  163.         char obuf[128];         /* output buffer */
  164.         int oblen;              /* length of output buffer */
  165.         static char errmsg[] = "ERROR - write failure in %s\n";
  166.  
  167.         if(!(inbuff=fopen(infile, "rb"))) {
  168.                 printf("Can't open %s\n", infile);
  169.                 return 0;
  170.         }
  171.         /* Initialization */
  172.         linect = 0;
  173.         crc = 0;
  174.         init_cr();
  175.         init_huff();
  176.  
  177.         /* Process header */
  178.         if(getx16(inbuff) != RECOGNIZE) {
  179.                 printf("%s is not a squeezed file\n", infile);
  180.                 goto closein;
  181.         }
  182.  
  183.         filecrc = getw16(inbuff);
  184.  
  185.         /* Get original file name */
  186.         p = outfile;                    /* send it to array */
  187.         do {
  188.                 *p = getc(inbuff);
  189.         } while(*p++ != '\0');
  190.  
  191.         printf("%s -> %s: ", infile, outfile);
  192.  
  193.  
  194.         numnodes = getw16(inbuff);
  195.  
  196.         if(numnodes < 0 || numnodes >= NUMVALS) {
  197.                 printf("%s has invalid decode tree size\n", infile);
  198.                 goto closein;
  199.         }
  200.  
  201.         /* Initialize for possible empty tree (SPEOF only) */
  202.         dnode[0].children[0] = -(SPEOF + 1);
  203.         dnode[0].children[1] = -(SPEOF + 1);
  204.  
  205.         /* Get decoding tree from file */
  206.         for(i = 0; i < numnodes; ++i) {
  207.                 dnode[i].children[0] = getw16(inbuff);
  208.                 dnode[i].children[1] = getw16(inbuff);
  209.         }
  210.  
  211.         if(dispcnt) {
  212.                 /* Use standard output for previewing */
  213.                 putchar('\n');
  214.                 while(((c = getcr(inbuff)) != EOF) && (linect < dispcnt)) {
  215.                         cc = 0x7f & c;  /* strip parity */
  216.                         if((cc < ' ') || (cc > '~'))
  217.                                 /* Unprintable */
  218.                                 switch(cc) {
  219.                                 case '\r':      /* return */
  220.                                         /* newline will generate CR-LF */
  221.                                         goto next;
  222.                                 case '\n':      /* newline */
  223.                                         ++linect;
  224.                                 case '\f':      /* formfeed */
  225.                                 case '\t':      /* tab */
  226.                                         break;
  227.                                 default:
  228.                                         cc = '.';
  229.                                 }
  230.                         putchar(cc);
  231.                 next: ;
  232.                 }
  233.                 if(ffflag)
  234.                         putchar('\f');  /* formfeed */
  235.         } else {
  236.                 /* Create output file */
  237.                 if(!(outbuff=fopen(outfile, "wb"))) {
  238.                         printf("Can't create %s\n", outfile);
  239.                         goto closeall;
  240.                 }
  241.                 printf("unsqueezing,");
  242.                 /* Get translated output bytes and write file */
  243.                 oblen = 0;
  244.                 while((c = getcr(inbuff)) != EOF) {
  245.                         crc += c;
  246.                         obuf[oblen++] = c;
  247.                         if (oblen >= sizeof(obuf)) {
  248.                                 if(!fwrite(obuf, sizeof(obuf), 1, outbuff)) {
  249.                                         printf(errmsg, outfile);
  250.                                         goto closeall;
  251.                                 }
  252.                                 oblen = 0;
  253.                         }
  254.                 }
  255.                 if (oblen && !fwrite(obuf, oblen, 1, outbuff)) {
  256.                         printf(errmsg, outfile);
  257.                         goto closeall;
  258.                 }
  259.  
  260.                 if((filecrc && 0xFFFF) != (crc && 0xFFFF))
  261.                         printf("ERROR - checksum error in %s\n", outfile);
  262.                 else    printf(" done.\n");
  263.  
  264.         closeall:
  265.                 fclose(outbuff);
  266.         }
  267.  
  268. closein:
  269.         fclose(inbuff);
  270. }
  271.  
  272. getw16(iob)                     /* get 16-bit word from file */
  273. FILE *iob;
  274. {
  275. int temp;
  276.  
  277. temp = getc(iob);               /* get low order byte */
  278. temp |= getc(iob) << 8;
  279. if (temp & 0x8000) temp |= (~0) << 15;  /* propogate sign for big ints */
  280. return temp;
  281.  
  282. }
  283.  
  284.  
  285. getx16(iob)                     /* get 16-bit (unsigned) word from file */
  286. FILE *iob;
  287. {
  288. int temp;
  289.  
  290. temp = getc(iob);               /* get low order byte */
  291. return temp | (int)(getc(iob) << 8);
  292.  
  293. }
  294.  
  295. /* initialize decoding functions */
  296.  
  297. init_cr()
  298. {
  299.         repct = 0;
  300. }
  301.  
  302. init_huff()
  303. {
  304.         bpos = 99;      /* force initial read */
  305. }
  306.  
  307. /* Get bytes with decoding - this decodes repetition,
  308.  * calls getuhuff to decode file stream into byte
  309.  * level code with only repetition encoding.
  310.  *
  311.  * The code is simple passing through of bytes except
  312.  * that DLE is encoded as DLE-zero and other values
  313.  * repeated more than twice are encoded as value-DLE-count.
  314.  */
  315.  
  316. int
  317. getcr(ib)
  318. FILE *ib;
  319. {
  320.         int c;
  321.  
  322.         if(repct > 0) {
  323.                 /* Expanding a repeated char */
  324.                 --repct;
  325.                 return value;
  326.         } else {
  327.                 /* Nothing unusual */
  328.                 if((c = getuhuff(ib)) != DLE) {
  329.                         /* It's not the special delimiter */
  330.                         value = c;
  331.                         if(value == EOF)
  332.                                 repct = LARGE;
  333.                         return value;
  334.                 } else {
  335.                         /* Special token */
  336.                         if((repct = getuhuff(ib)) == 0)
  337.                                 /* DLE, zero represents DLE */
  338.                                 return DLE;
  339.                         else {
  340.                                 /* Begin expanding repetition */
  341.                                 repct -= 2;     /* 2nd time */
  342.                                 return value;
  343.                         }
  344.                 }
  345.         }
  346. }
  347.  
  348. /* eject^Leject */
  349.  
  350. /* Decode file stream into a byte level code with only
  351.  * repetition encoding remaining.
  352.  */
  353.  
  354. int
  355. getuhuff(ib)
  356. FILE *ib;
  357. {
  358.         int i;
  359.  
  360.         /* Follow bit stream in tree to a leaf*/
  361.         i = 0;  /* Start at root of tree */
  362.         do {
  363.                 if(++bpos > 7) {
  364.                         if((curin = getc(ib)) == ERROR)
  365.                                 return ERROR;
  366.                         bpos = 0;
  367.                         /* move a level deeper in tree */
  368.                         i = dnode[i].children[1 & curin];
  369.                 } else
  370.                         i = dnode[i].children[1 & (curin >>= 1)];
  371.         } while(i >= 0);
  372.  
  373.         /* Decode fake node index to original data value */
  374.         i = -(i + 1);
  375.         /* Decode special endfile token to normal EOF */
  376.         i = (i == SPEOF) ? EOF : i;
  377.         return i;
  378. }
  379.